package cn.lg.soar.common.util.data;

import java.time.LocalDateTime;
import java.time.temporal.TemporalUnit;
import java.util.*;
import java.util.stream.Collectors;

import static cn.lg.soar.common.constant.SymbolConstants.COMMON_CHARS;

/**
 * 基于 Random
 * @author luguoxiang
 * @date 2021/8/23
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public interface RandomUtil {

    Random RANDOM = new Random();

    /**
     * 获取uuid
     * @return
     */
    static String uuid() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 随机布尔值
     * @return
     */
    static boolean getBoolean() {
        return RANDOM.nextBoolean();
    }

    /**
     * 随机生成一个int值
     * @param min
     * @param max
     * @return
     */
    static int getInt(int min, int max) {
        return RandomUtil.RANDOM.nextInt(max - min) + min;
    }

    /**
     * 随机生成一个int值
     * @param max
     * @return
     */
    static int getInt(int max) {
        return RandomUtil.RANDOM.nextInt(max);
    }

    /**
     * 随机生成一个int值
     * @return
     */
    static int getInt() {
        return RandomUtil.RANDOM.nextInt();
    }

    /**
     * 获取long数据
     * @return
     */
    static long getLong() {
        return RANDOM.nextLong();
    }

    /**
     * 获取float数据
     * @return
     */
    static float getFloat() {
        return RANDOM.nextFloat();
    }

    /**
     * 获取double数据
     * @return
     */
    static double getDouble() {
        return RANDOM.nextDouble();
    }

    /**
     * 获取一个时间
     * @return
     */
    static LocalDateTime getDatetime() {
        int anInt = RANDOM.nextInt();
        return LocalDateTime.now().plusSeconds(anInt);
    }

    /**
     * 生日
     * @param minAge 最小年龄
     * @param maxAge 最大年龄
     * @param unit 年龄单位
     * @return
     */
    static LocalDateTime getBirthday(int minAge, int maxAge, TemporalUnit unit) {
        int age = getInt(minAge, maxAge);
        return LocalDateTime.now().minus(age, unit);
    }

    /**
     * 生日
     * @param minAge 最小年龄（单位：年）
     * @param maxAge 最小年龄（单位：年）
     * @return
     */
    static LocalDateTime getBirthday(int minAge, int maxAge) {
        int age = getInt(minAge, maxAge);
        return LocalDateTime.now().minusYears(age);
    }

    /**
     * 生成一个随机的int数组
     * @param length 数组长度
     * @param min 数组元素的最小值
     * @param max 数组元素的最大值
     * @return
     */
    static int[] getIntArray(int length, int min, int max) {
        int[] ints = new int[ length ];
        for (;length > 0;) {
            ints[ --length ] = RandomUtil.RANDOM.nextInt(max - min) + min;
        }
        return ints;
    }

    /**
     * 生成一个随机的int数组
     * @param min 数组元素的最小值
     * @param max 数组元素的最大值
     * @return
     */
    static int[] getIntArray(int min, int max) {
        return RandomUtil.getIntArray(
                RandomUtil.getInt(0, 2000),
                min,
                max
        );
    }

    /**
     * 生成一个随机的int数组
     * @param length 数组长度
     * @return
     */
    static int[] getIntArray(int length) {
        return RandomUtil.getIntArray(length, 0, Integer.MAX_VALUE);
    }

    /**
     * 生成一个随机的int数组
     * @return
     */
    static int[] getIntArray() {
        return RandomUtil.getIntArray(RandomUtil.getInt(2000));
    }

    /**
     * 生成一个随机的long数组
     * @param length 数组长度
     * @param min 数组元素的最小值
     * @param max 数组元素的最大值
     * @return
     */
    static long[] getLongArray(int length, int min, int max) {
        long[] longs = new long[ length ];
        for (;length > 0;) {
            longs[ --length ] = RandomUtil.RANDOM.nextInt(max - min) + min;
        }
        return longs;
    }

    /**
     * 生成一个随机的long数组
     * @param min 数组元素的最小值
     * @param max 数组元素的最大值
     * @return
     */
    static long[] getLongArray(int min, int max) {
        return RandomUtil.getLongArray(
                RandomUtil.getInt(0, 2000),
                min,
                max
        );
    }

    /**
     * 生成一个随机的long数组
     * @param length 数组长度
     * @return
     */
    static long[] getLongArray(int length) {
        long[] longs = new long[ length ];
        for (;length > 0;) {
            longs[ --length ] = RandomUtil.RANDOM.nextLong();
        }
        return longs;
    }

    /**
     * 生成一个随机的long数组
     * @return long[]
     */
    static long[] getLongArray() {
        return RandomUtil.getLongArray(RandomUtil.getInt(2000));
    }

    /**
     * 从字符数组中生成随机字符串
     * @param length 字符串长度
     * @param source 字符源
     * @return
     */
    static String getString(int length, char...source) {
        char[] chars = new char[length];
        int max = source.length;
        for (int i = 0; i < length; i++) {
            int index = getInt(max);
            chars[i] = source[index];
        }
        return new String(chars);
    }

    /**
     * 从字符数组中生成随机长度的随机字符串
     * @param minLength 字符串最小长度
     * @param maxLength 字符串最大长度
     * @param source 字符源
     * @return
     */
    static String getString(int minLength, int maxLength, char...source) {
        return getString(getInt(minLength, maxLength), source);
    }

    /**
     * 从字符数组中生成随机长度的随机字符串
     * @param minLength 字符串最小长度
     * @param maxLength 字符串最大长度
     * @return
     */
    static String getString(int minLength, int maxLength) {
        return getString(minLength, maxLength, COMMON_CHARS);
    }

    /**
     * 从提供的字符串中随机获取字符生成新的字符串
     * @param minLength 字符串最小长度
     * @param maxLength 字符串最大长度
     * @param source 字符源
     * @return
     */
    static String getString(int minLength, int maxLength, String source) {
        return getString(minLength, maxLength, source.toCharArray());
    }

    /**
     * 从提供的字符串中随机获取字符生成新的字符串
     * @param length 生成的字符串长度
     * @param source 字符源
     * @return
     */
    static String getString(int length, String source) {
        return getString(length, source.toCharArray());
    }

    /**
     * 随机验证码实现
     * @param length 验证码字符数
     * @return
     */
    static String getString(int length) {
        return getString(length, COMMON_CHARS);
    }

    /**
     * 随机获取元素
     * @param list
     * @param <T>
     * @return
     */
    static <T>T getElement(List<T> list) {
        return list.get(getInt(list.size()));
    }

    /**
     * 随机获取元素，并移除获取的元素
     * @param list
     * @param <T>
     * @return
     */
    static <T>T getElementAndRemove(List<T> list) {
        T t = list.get(getInt(list.size()));
        list.removeIf(t::equals);
        return t;
    }

    /**
     * 随机获取元素
     * @param collection
     * @param <T>
     * @return
     */
    static <T>T getElement(Collection<T> collection) {
        return getElement(new ArrayList<>(collection));
    }

    /**
     * 随机获取元素
     * @param array
     * @param <T>
     * @return
     */
    @SafeVarargs
    static <T>T getElement(T ...array) {
        return getElement(Arrays.stream(array).collect(Collectors.toList()));
    }

    /**
     * 随机获取多个元素
     * @param quantity
     * @param list
     * @param <T>
     * @return
     */
    static <T>List<T> getElements(int quantity, List<T> list) {
        if (quantity > list.size()) {
            quantity = list.size();
        }
        List<T> rs = new ArrayList<>(quantity);
        list = new ArrayList<>(list);
        for (int i = 0; i < quantity; i++) {
            T t = list.get(getInt(list.size()));
            list.removeIf(t::equals);
            rs.add(t);
        }
        return rs;
    }

    /**
     * 随机获取多个元素，并移除获取到的数据
     * @param quantity
     * @param list
     * @param <T>
     * @return
     */
    static <T>List<T> getElementsAndRemove(int quantity, List<T> list) {
        if (quantity > list.size()) {
            quantity = list.size();
        }
        List<T> rs = new ArrayList<>(quantity);
        for (int i = 0; i < quantity; i++) {
            T t = list.get(getInt(list.size()));
            list.removeIf(t::equals);
            rs.add(t);
        }
        return rs;
    }

    /**
     * 随机获取多个元素
     * @param quantity
     * @param collection
     * @param <T>
     * @return
     */
    static <T>List<T> getElements(int quantity, Collection<T> collection) {
        return getElements(quantity, new ArrayList<>(collection));
    }

    /**
     * 随机获取多个元素
     * @param quantity
     * @param array
     * @param <T>
     * @return
     */
    @SafeVarargs
    static <T>List<T> getElements(int quantity, T ...array) {
        return getElements(quantity, Arrays.stream(array).collect(Collectors.toList()));
    }

    /**
     * 获取字节数组
     * @param len
     * @return
     */
    static byte[] getBytes(int len) {
        if (len <= 0) {
            throw new IllegalArgumentException("Length must be >= 0");
        }
        byte[] result = new byte[len];
        RANDOM.nextBytes(result);
        return result;
    }

    /**
     * 获取字节数组
     * @param minLen
     * @param maxLen
     * @return
     */
    static byte[] getBytes(int minLen, int maxLen) {
        if (minLen <= 0 || maxLen <= 0) {
            throw new IllegalArgumentException("Length must be >= 0");
        }
        if (minLen > maxLen) {
            minLen = getInt(maxLen, minLen);
        } else {
            minLen = getInt(minLen, maxLen);
        }
        byte[] result = new byte[minLen];
        RANDOM.nextBytes(result);
        return result;
    }

}
